home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swags_z.zip / STRINGS.SWG / 0079_Word Strings-64K.pas < prev    next >
Pascal/Delphi Source File  |  1994-05-26  |  24KB  |  814 lines

  1. {$S-,R-,V-,I-,B-,F+}
  2.  
  3. {$IFNDEF Ver40}
  4.   {$I OPLUS.INC}
  5. {$ENDIF}
  6.  
  7. {*********************************************************}
  8. {*                  TPWRDSTR.PAS 1.0                     *}
  9. {*          Copyright (c) Ken Henderson 1990.            *}
  10. {*                                                       *}
  11. {*                                                       *}
  12. {*                 All rights reserved.                  *}
  13. {*********************************************************}
  14.  
  15. unit TPWrdStr;
  16.   {-Routines to support strings which use a word in the place of Turbo Pascal's
  17.     byte for holding the length of a string -- theoretically allowing strings
  18.     as large as 64k.}
  19.  
  20. interface
  21.  
  22. uses
  23.   TpString;
  24.  
  25. const
  26.   MaxWrdStr = 1024;          {Maximum length of WrdStr - increase up to 65519}
  27.   NotFound = 0;              {Returned by the Pos functions if substring not found}
  28.  
  29. type
  30.   WrdStr = array[-1..MaxWrdStr] of Char;
  31.   WrdStrPtr = ^WrdStr;
  32.  
  33. function WrdStr2Str(var A : WrdStr) : string;
  34.   {-Convert WrdStr to Turbo string, truncating if longer than 255 chars}
  35.  
  36. procedure Str2WrdStr(S : string; var A : WrdStr);
  37.   {-Convert a Turbo string into an WrdStr}
  38.  
  39. function LenWrdStr(A : WrdStr) : Word;
  40.   {-Return the length of an WrdStr string}
  41.  
  42. procedure CopyWrdStr(var A : WrdStr; Start, Len : Word; var O : WrdStr);
  43.   {-Return a substring of a. Note start=1 for first char in a}
  44.  
  45. procedure DeleteWrdStr(var A : WrdStr; Start, Len : Word);
  46.   {-Delete len characters of a, starting at position start}
  47.  
  48. procedure ConcatWrdStr(var A, B, C : WrdStr);
  49.   {-Concatenate two WrdStr strings, returning a third}
  50.  
  51. procedure ConcatStr(var A : WrdStr; S : string; var C : WrdStr);
  52.   {-Concatenate a string to an WrdStr, returning a new WrdStr}
  53.  
  54. procedure InsertWrdStr(var Obj, A : WrdStr; Start : Word);
  55.   {-Insert WrdStr obj at position start of a}
  56.  
  57. procedure InsertStr(Obj : string; var A : WrdStr; Start : Word);
  58.   {-Insert string obj at position start of a}
  59.  
  60. function PosStr(Obj : string; var A : WrdStr) : Word;
  61.   {-Return the position of the string obj in a, returning NotFound if not found}
  62.  
  63. function PosWrdStr(var Obja, A : WrdStr) : Word;
  64.   {-Return the position of obja in a, returning NotFound if not found}
  65.  
  66. function WrdStrToHeap(var A : WrdStr) : WrdStrPtr;
  67.   {-Put WrdStr on heap, returning a pointer, nil if insufficient memory}
  68.  
  69. procedure WrdStrFromHeap(P : WrdStrPtr; var A : WrdStr);
  70.   {-Return an WrdStr from the heap, empty if pointer is nil}
  71.  
  72. procedure DisposeWrdStr(P : WrdStrPtr);
  73.   {-Dispose of heap space pointed to by P}
  74.  
  75. function ReadLnWrdStr(var F : Text; var A : WrdStr) : Boolean;
  76.   {-Read an WrdStr from text file, returning true if successful}
  77.  
  78. function WriteWrdStr(var F : Text; var A : WrdStr) : Boolean;
  79.   {-Write an WrdStr to text file, returning true if successful}
  80.  
  81. procedure WrdStrUpcase(var A, B : WrdStr);
  82.   {-Uppercase the WrdStr in a, returning b}
  83.  
  84. procedure WrdStrLocase(var A, B : WrdStr);
  85.   {-Lowercase the WrdStr in a, returning b}
  86.  
  87. procedure WrdStrCharStr(Ch : Char; Len : Word; var A : WrdStr);
  88.   {-Return an WrdStr of length len filled with ch}
  89.  
  90. procedure WrdStrPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  91.   {-Right-pad the WrdStr in a to length len with ch, returning b}
  92.  
  93. procedure WrdStrPad(var A : WrdStr; Len : Word; var B : WrdStr);
  94.   {-Right-pad the WrdStr in a to length len with blanks, returning b}
  95.  
  96. procedure WrdStrLeftPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  97.   {-Left-pad the WrdStr in a to length len with ch, returning b}
  98.  
  99. procedure WrdStrLeftPad(var A : WrdStr; Len : Word; var B : WrdStr);
  100.   {-Left-pad the WrdStr in a to length len with blanks, returning b}
  101.  
  102. procedure WrdStrTrimLead(var A, B : WrdStr);
  103.   {-Return an WrdStr with leading white space removed}
  104.  
  105. procedure WrdStrTrimTrail(var A, B : WrdStr);
  106.   {-Return an WrdStr with trailing white space removed}
  107.  
  108. procedure WrdStrTrim(var A, B : WrdStr);
  109.   {-Return an WrdStr with leading and trailing white space removed}
  110.  
  111. procedure WrdStrCenterCh(var A : WrdStr; Ch : Char; Width : Word; var B : WrdStr);
  112.   {-Return an WrdStr centered in an WrdStr of Ch with specified width}
  113.  
  114. procedure WrdStrCenter(var A : WrdStr; Width : Word; var B : WrdStr);
  115.   {-Return an WrdStr centered in an WrdStr of blanks with specified width}
  116.  
  117. function CompWrdStr(var a1, a2 : WrdStr) : Boolean;
  118.   {-Return equivalence of a1 and a2}
  119.  
  120.   {==========================================================================}
  121.  
  122. implementation
  123. const
  124.  Blank : char = #32;
  125.  
  126.   function WrdStr2Str(var A : WrdStr) : string;
  127.     {-Convert WrdStr to Turbo string, truncating if longer than 255 chars}
  128.   var
  129.     S : string;
  130.     Len : Word absolute A;
  131.     Slen : byte Absolute S;
  132.   begin
  133.     if Len > 255 then SLen := 255
  134.     else Slen := Len;
  135.     Move(A[1], S[1], SLen);
  136.     WrdStr2Str := S;
  137.   end;
  138.  
  139.   procedure Str2WrdStr(S : string; var A : WrdStr);
  140.     {-Convert a Turbo string into an WrdStr}
  141.   var
  142.     slen : byte absolute S;
  143.     alen : word absolute A;
  144.   begin
  145.     Move(S[1], A[1], slen);
  146.     alen := slen;
  147.   end;
  148.  
  149.   function LenWrdStr(A : WrdStr) : Word;
  150.     {-Return the length of an WrdStr string}
  151.   var
  152.     alen : Word absolute A;
  153.   begin
  154.     LenWrdStr := alen;
  155.   end;
  156.  
  157.   procedure CopyWrdStr(var A : WrdStr; Start, Len : Word; var O : WrdStr);
  158.     {-Return a substring of a. Note start=1 for first char in a}
  159.   var
  160.     alen : Word absolute A;
  161.     olen : Word absolute O;
  162.   begin
  163.     if Start > alen then
  164.       Olen := 0
  165.     else begin
  166.       {Don't copy more than exists}
  167.       if Start+Len > alen then
  168.         Len := Succ(alen-Start);
  169.       Move(A[Start], O[1], Len);
  170.       Olen := Len;
  171.     end;
  172.   end;
  173.  
  174.   procedure DeleteWrdStr(var A : WrdStr; Start, Len : Word);
  175.     {-Delete len characters of a, starting at position start}
  176.   var
  177.     alen : Word Absolute A;
  178.     mid : Word;
  179.   begin
  180.     if Start <= alen then begin
  181.       {Don't do anything if start position exceeds length of string}
  182.       mid := Start+Len;
  183.       if mid <= alen then begin
  184.         {Move right remainder of string left}
  185.         Move(A[mid], A[Start], len);
  186.         Dec(alen,len);
  187.       end else
  188.         {Entire end of string deleted}
  189.         alen := Pred(Start);
  190.     end;
  191.   end;
  192.  
  193.   procedure ConcatWrdStr(var A, B, C : WrdStr);
  194.     {-Concatenate two WrdStr strings, returning a third}
  195.   var
  196.     alen : Word absolute A;
  197.     blen : Word absolute B;
  198.     clen : Word absolute C;
  199.     temp : Word;
  200.   begin
  201.  
  202.     {Put a into the result}
  203.     Move(A[1], C[1], alen);
  204.  
  205.     {Store as much of b as fits into result}
  206.     Temp := blen;
  207.     if alen+blen > MaxWrdStr then
  208.       Temp := MaxWrdStr-alen;
  209.     Move(B[1], C[Succ(alen)], Temp);
  210.  
  211.     {Terminate the result}
  212.     clen := alen+blen;
  213.   end;
  214.  
  215.   procedure ConcatStr(var A : WrdStr; S : string; var C : WrdStr);
  216.     {-Concatenate a string to an WrdStr, returning a new WrdStr}
  217.   var
  218.     alen : Word absolute A;
  219.     clen : Word absolute C;
  220.     slen : Byte absolute S;
  221.   begin
  222.  
  223.     {Put a into the result}
  224.     Move(A[1], C[1], alen);
  225.  
  226.     {Store as much of s as fits into result}
  227.     if alen+slen > MaxWrdStr then
  228.       slen := MaxWrdStr-alen;
  229.     Move(S[1], C[succ(alen)], slen);
  230.  
  231.     {Terminate the result}
  232.     clen := alen+slen;
  233.   end;
  234.  
  235.   procedure InsertWrdStr(var Obj, A : WrdStr; Start : Word);
  236.     {-Insert WrdStr obj at position start of a}
  237.   var
  238.     alen : Word absolute A;
  239.     olen : Word absolute Obj;
  240.     mid, temp : Word;
  241.   begin
  242.  
  243.     if Start > alen then
  244.       {Concatenate if start exceeds alen}
  245.       Start := Succ(alen)
  246.  
  247.     else begin
  248.       {Move right side characters right to make space for insert}
  249.       mid := Start+olen;
  250.       if mid <= MaxWrdStr then
  251.         {Room for at least some of the right side characters}
  252.         if alen+olen <= MaxWrdStr then
  253.           {Room for all of the right side}
  254.           Move(A[Start], A[mid], Succ(alen-Start))
  255.         else
  256.           {Room for part of the right side}
  257.           Move(A[Start], A[mid], Succ(MaxWrdStr-mid));
  258.     end;
  259.  
  260.     {Insert the obj string}
  261.     temp := Olen;
  262.     if Start+olen > MaxWrdStr then
  263.       temp := Succ(MaxWrdStr-Start);
  264.     Move(Obj[1], A[Start], temp);
  265.  
  266.     {Terminate the string}
  267.     if alen+olen <= MaxWrdStr then
  268.       Inc(alen,olen)
  269.     else
  270.       alen := MaxWrdStr;
  271.   end;
  272.  
  273.   procedure InsertStr(Obj : string; var A : WrdStr; Start : Word);
  274.     {-Insert string obj at position start of a}
  275.   var
  276.     alen : Word absolute A;
  277.     olen : byte absolute Obj;
  278.     mid,temp : Word;
  279.   begin
  280.  
  281.     if Start > alen then
  282.       {Concatenate if start exceeds alen}
  283.       Start := succ(alen)
  284.  
  285.     else begin
  286.       {Move right side characters right to make space for insert}
  287.       mid := Start+olen;
  288.       if mid <= MaxWrdStr then
  289.         {Room for at least some of the right side characters}
  290.         if alen+olen <= MaxWrdStr then
  291.           {Room for all of the right side}
  292.           Move(A[Start], A[mid], Succ(alen-Start))
  293.         else
  294.           {Room for part of the right side}
  295.           Move(A[Start], A[mid], Succ(MaxWrdStr-mid));
  296.     end;
  297.  
  298.     {Insert the obj string}
  299.     temp := olen;
  300.     if Start+olen > MaxWrdStr then
  301.       temp := Succ(MaxWrdStr-Start);
  302.     Move(Obj[1], A[Start], temp);
  303.  
  304.     {Terminate the string}
  305.     if alen+olen <= MaxWrdStr then
  306.       Inc(alen,olen)
  307.     else
  308.       alen := MaxWrdStr;
  309.   end;
  310.  
  311.   {$L TPWrdStr}
  312.   function Search(var Buffer; BufLength : Word; var Match; MatLength : Word) : Word;
  313.     external;
  314.   procedure WrdStrUpcase(var A, B : WrdStr);
  315.     {-Upper case WrdStr A, returning it in B}
  316.   var
  317.     alen : Word absolute A;
  318.     x : Word;
  319.   begin
  320.     For x:=1 to alen do A[x]:=UpCase(A[x]);
  321.     Move(A,B,alen+2);
  322.   end;
  323.   procedure WrdStrLocase(var A, B : WrdStr);
  324.     {-Lower case WrdStr A, returning it in B}
  325.   var
  326.     alen : Word absolute A;
  327.     x : Word;
  328.   begin
  329.     For x:=1 to alen do A[x]:=LoCase(A[x]);
  330.     Move(A,B,alen+2);
  331.   end;
  332.  
  333.   function CompWrdStr(var a1, a2 : WrdStr) : Boolean;
  334.     {-Compare WrdStr's a1 and a2 and return equivalence}
  335.   var
  336.    alen1 : Word absolute A1;
  337.    alen2 : Word absolute A2;
  338.    x : Word;
  339.   begin
  340.     CompWrdStr := false;
  341.     If (alen1=alen2) then  {possibly equal, let's check it out}
  342.     begin
  343.       for x:=1 to alen1 do if (A1[x]<>A2[x]) then exit;
  344.       CompWrdStr := true;  {If we made it to here, they must be equal}
  345.     end;
  346.   end;
  347.  
  348.   function PosStr(Obj : string; var A : WrdStr) : Word;
  349.     {-Return the position of the string obj in a, returning NotFound if not found}
  350.   var
  351.     alen : Word absolute A;
  352.     olen : Byte absolute Obj;
  353.     PosFound : Word;
  354.   begin
  355.     PosFound := Search(A[1], alen, Obj[1], olen);
  356.     If (PosFound = $FFFF) then {Search didn't find it}
  357.        PosFound := 0;
  358.     PosStr := Succ(PosFound);
  359.   end;
  360.  
  361.   function PosWrdStr(var Obja, A : WrdStr) : Word;
  362.     {-Return the position of obja in a, returning NotFound if not found}
  363.   var
  364.     alen : Word absolute A;
  365.     olen : Word absolute Obja;
  366.     PosFound : Word;
  367.   begin
  368.     PosFound := Search(A[1], alen, Obja[1], olen);
  369.     If (PosFound = $FFFF) then {Search didn't find it}
  370.        PosFound := 0;
  371.     PosWrdStr := Succ(PosFound);
  372.   end;
  373.  
  374.   function WrdStrToHeap(var A : WrdStr) : WrdStrPtr;
  375.     {-Put WrdStr on heap, returning a pointer, nil if insufficient memory}
  376.   var
  377.     alen : Word;
  378.     P : WrdStrPtr;
  379.   begin
  380.     alen := LenWrdStr(A)+2;
  381.     if MaxAvail >= alen then begin
  382.       GetMem(P, alen);
  383.       Move(A, P^, alen);
  384.       WrdStrToHeap := P;
  385.     end else
  386.       WrdStrToHeap := nil;
  387.   end;
  388.  
  389.   procedure WrdStrFromHeap(P : WrdStrPtr; var A : WrdStr);
  390.     {-Return an WrdStr from the heap, empty if pointer is nil}
  391.   var
  392.     alen : Word absolute a;
  393.     plen : Word absolute p;
  394.   begin
  395.     if P = nil then
  396.       Alen := 0
  397.     else
  398.       Move(P^, A, Plen+2);
  399.   end;
  400.  
  401.   procedure DisposeWrdStr(P : WrdStrPtr);
  402.     {-Dispose of heap space pointed to by P}
  403.   begin
  404.     if P <> nil then
  405.       FreeMem(P, LenWrdStr(P^)+2);
  406.   end;
  407.  
  408.   procedure WrdStrCharStr(Ch : Char; Len : Word; var A : WrdStr);
  409.     {-Return an WrdStr of length len filled with ch}
  410.   var
  411.     alen : Word absolute A;
  412.   begin
  413.     if Len = 0 then
  414.       Alen := 0
  415.     else begin
  416.       if Len > MaxWrdStr then
  417.         Len := MaxWrdStr;
  418.       FillChar(A[1], Len, Ch);
  419.       Alen := Len;
  420.     end;
  421.   end;
  422.  
  423.   procedure WrdStrPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  424.     {-Right-pad the WrdStr to length len with ch, returning b}
  425.   var
  426.     alen : Word Absolute A;
  427.     blen : Word Absolute B;
  428.   begin
  429.     if alen >= Len then
  430.       {Return the input string}
  431.       Move(A, B, alen+2)
  432.     else begin
  433.       if Len > MaxWrdStr then
  434.         Len := MaxWrdStr;
  435.       Move(A[1], B[1], alen);
  436.       FillChar(B[succ(alen)], Len-alen, Ch);
  437.       Blen := len;
  438.     end;
  439.   end;
  440.  
  441.   procedure WrdStrPad(var A : WrdStr; Len : Word; var B : WrdStr);
  442.     {-Right-pad the WrdStr to length len with blanks, returning b}
  443.   begin
  444.     WrdStrPadCh(A, Blank, Len, B);
  445.   end;
  446.  
  447.   procedure WrdStrLeftPadCh(var A : WrdStr; Ch : Char; Len : Word; var B : WrdStr);
  448.     {-Left-pad the WrdStr in a to length len with ch, returning b}
  449.   var
  450.     alen : Word absolute A;
  451.     blen : Word absolute B;
  452.   begin
  453.     if alen >= Len then
  454.       {Return the input string}
  455.       Move(A, B, alen+2)
  456.     else begin
  457.       FillChar(B[1], Len-alen, Ch);
  458.       Move(A[1], B[Succ(Len-alen)], alen);
  459.       BLen := Len;
  460.     end;
  461.   end;
  462.  
  463.   procedure WrdStrLeftPad(var A : WrdStr; Len : Word; var B : WrdStr);
  464.     {-Left-pad the WrdStr in a to length len with blanks, returning b}
  465.   begin
  466.     WrdStrLeftPadCh(A, Blank, Len, B);
  467.   end;
  468.  
  469.   procedure WrdStrTrimLead(var A, B : WrdStr);
  470.     {-Return an WrdStr with leading white space removed}
  471.   var
  472.     alen : Word absolute A;
  473.     apos : Word;
  474.   begin
  475.     apos := 1;
  476.     while (apos < alen) and (A[apos] <= Blank) do
  477.       Inc(apos);
  478.     Move(A[apos], B[1], Succ(alen-apos));
  479.   end;
  480.  
  481.   procedure WrdStrTrimTrail(var A, B : WrdStr);
  482.     {-Return an WrdStr with trailing white space removed}
  483.   var
  484.     alen : Word absolute A;
  485.     blen : Word absolute B;
  486.   begin
  487.     while (alen > 1) and (A[Pred(alen)] <= Blank) do
  488.       Dec(alen);
  489.     Move(A, B, alen+2);
  490.   end;
  491.  
  492.   procedure WrdStrTrim(var A, B : WrdStr);
  493.     {-Return an WrdStr with leading and trailing white space removed}
  494.   var
  495.     blen : Word Absolute B;
  496.   begin
  497.     WrdStrTrimLead(A, B);
  498.     while (blen > 1) and (B[Pred(blen)] <= Blank) do
  499.       Dec(blen);
  500.   end;
  501.  
  502.   procedure WrdStrCenterCh(var A : WrdStr; Ch : Char; Width : Word; var B : WrdStr);
  503.     {-Return an WrdStr centered in an WrdStr of Ch with specified width}
  504.   var
  505.     alen : Word absolute A;
  506.     blen : Word absolute B;
  507.   begin
  508.     if alen >= Width then
  509.       {Return input}
  510.       Move(A, B, alen+2)
  511.     else begin
  512.       FillChar(B[1], Width, Ch);
  513.       Move(A[1], B[Succ((Width-alen) shr 1)], alen);
  514.       Blen := Width;
  515.     end;
  516.   end;
  517.  
  518.   procedure WrdStrCenter(var A : WrdStr; Width : Word; var B : WrdStr);
  519.     {-Return an WrdStr centered in an WrdStr of blanks with specified width}
  520.   begin
  521.     WrdStrCenterCh(A, Blank, Width, B);
  522.   end;
  523.  
  524. type
  525.   {text buffer}
  526.   TextBuffer = array[0..65520] of Byte;
  527.  
  528.   {structure of a Turbo File Interface Block}
  529.   FIB = record
  530.           Handle : Word;
  531.           Mode : Word;
  532.           BufSize : Word;
  533.           Private : Word;
  534.           BufPos : Word;
  535.           BufEnd : Word;
  536.           BufPtr : ^TextBuffer;
  537.           OpenProc : Pointer;
  538.           InOutProc : Pointer;
  539.           FlushProc : Pointer;
  540.           CloseProc : Pointer;
  541.           UserData : array[1..16] of Byte;
  542.           Name : array[0..79] of Char;
  543.           Buffer : array[0..127] of Char;
  544.         end;
  545.  
  546. const
  547.   FMClosed = $D7B0;
  548.   FMInput = $D7B1;
  549.   FMOutput = $D7B2;
  550.   FMInOut = $D7B3;
  551.   CR : Char = ^M;
  552.  
  553.   function ReadLnWrdStr(var F : Text; var A : WrdStr) : Boolean;
  554.     {-Read an WrdStr from text file, returning true if successful}
  555.   var
  556.     CrPos : Word;
  557.     alen : Word absolute A;
  558.     blen : Word;
  559.  
  560.     function RefillBuf(var F : Text) : Boolean;
  561.       {-Refill buffer}
  562.     var
  563.       Ch : Char;
  564.     begin
  565.       with FIB(F) do begin
  566.         BufEnd := 0;
  567.         BufPos := 0;
  568.         Read(F, Ch);
  569.         if IoResult <> 0 then begin
  570.           {Couldn't read from file}
  571.           RefillBuf := False;
  572.           Exit;
  573.         end;
  574.         {Reset the buffer again}
  575.         BufPos := 0;
  576.         RefillBuf := True;
  577.       end;
  578.     end;
  579.  
  580.  
  581.   begin
  582.     with FIB(F) do begin
  583.  
  584.       {Initialize the WrdStr length and function result}
  585.       alen := 0;
  586.       ReadLnWrdStr := False;
  587.  
  588.       {Make sure file open for input}
  589.       if Mode <> FMInput then
  590.         Exit;
  591.  
  592.       {Make sure something is in buffer}
  593.       if BufPos >= BufEnd then
  594.         if not(RefillBuf(F)) then
  595.           Exit;
  596.  
  597.       {Use the Turbo text file buffer to build the WrdStr}
  598.       repeat
  599.  
  600.         {Search for the next carriage return in the file buffer}
  601.         CrPos := Search(BufPtr^[BufPos], Succ(BufEnd-BufPos), CR, 1);
  602.  
  603.         if CrPos = $FFFF then begin
  604.           {CR not found, save the portion of the buffer seen so far}
  605.           blen := BufEnd-BufPos;
  606.           if alen+blen > MaxWrdStr then
  607.             blen := MaxWrdStr-alen;
  608.  
  609.           Move(BufPtr^[BufPos], A[alen], blen);
  610.           Inc(alen, blen);
  611.  
  612.           {See if at end of file}
  613.           if eof(F) then begin
  614.             {Force exit with this line}
  615.             CrPos := 0;
  616.             {Remove trailing ^Z}
  617.             while (alen > 1) and (A[Pred(alen)] = ^Z) do
  618.               Dec(alen);
  619.           end else if not(RefillBuf(F)) then
  620.             Exit;
  621.  
  622.         end else begin
  623.           {Save up to the CR}
  624.           blen := CrPos;
  625.           if alen+blen > MaxWrdStr then
  626.             blen := MaxWrdStr-alen;
  627.           Move(BufPtr^[BufPos], A[alen], blen);
  628.           Inc(alen, blen);
  629.  
  630.           {Inform Turbo we used the characters}
  631.           Inc(BufPos, Succ(CrPos));
  632.  
  633.           {Skip over following ^J}
  634.           if BufPos < BufEnd then begin
  635.             {Next character is within current buffer}
  636.             if BufPtr^[BufPos] = Ord(^J) then
  637.               Inc(BufPos);
  638.           end else begin
  639.             {Next character is not within current buffer}
  640.             {Refill the buffer}
  641.             if not(RefillBuf(F)) then
  642.               Exit;
  643.             if BufPos < BufEnd then
  644.               if BufPtr^[BufPos] = Ord(^J) then
  645.                 Inc(BufPos);
  646.           end;
  647.  
  648.         end;
  649.  
  650.       until (CrPos <> $FFFF) or (alen > MaxWrdStr);
  651.  
  652.       {Return success and terminate the WrdStr}
  653.       ReadLnWrdStr := True;
  654.  
  655.     end;
  656.   end;
  657.  
  658.   function WriteWrdStr(var F : Text; var A : WrdStr) : Boolean;
  659.     {-Write an WrdStr to text file, returning true if successful}
  660.   var
  661.     S : string;
  662.     alen : Word absolute A;
  663.     apos : Word;
  664.     slen : Byte absolute S;
  665.   begin
  666.     apos := 1;
  667.     WriteWrdStr := False;
  668.  
  669.     {Write the WrdStr as a series of strings}
  670.     while apos < alen do begin
  671.       slen := alen-apos;
  672.       if slen > 255 then
  673.         slen := 255;
  674.       Move(A[apos], S[1], slen);
  675.       Write(F, S);
  676.       if IoResult <> 0 then
  677.         Exit;
  678.       Inc(apos, slen);
  679.     end;
  680.  
  681.     WriteWrdStr := True;
  682.   end;
  683.  
  684. end.
  685.  
  686.  
  687. { -----------------    XX3402 Code for TPWRDSTR.OBJ ------------------}
  688. { Cut HERE and save save to a files (TPWRDSTR.XX).  From DOS execute:
  689. {               XX3402 D TPWRDSTR.XX to create TPWRDSTR.OBJ           }
  690.  
  691. *XX3402-000257-280390--72--85-53814----TPWRDSTR.OBJ--1-OF--1
  692. U+s+13FEJp72IpFG9Y3HHQq66++++3FpQa7j623nQqJhMalZQW+UJaJmQqZjPW+l9X+lW6UI
  693. +21dk9Bw3+lII3RGF3BIIWt-IoqHW-E+ECaU83gG13FEEoxBHIxC9Y3HHLu6+k-+uImK+U++
  694. O7M4++F1HoF3FNU5+0V0++6-+TCA4E+8JJ-1EJB3I377HE+8H2x1EJB3I377HE-TY+o+++24
  695. IoJ-IYB6++++dcU2+20W+N4UFU+-++-JWykSzAFy1cjTWosAWpM4VR7o7AJq08l88wdq4z8i
  696. RFS3obEAIJRKWwfndZtTKLLgHsj58wDf+nD+G-y9tJr80U+VWU6++5E+
  697. ***** END OF BLOCK 1 *****
  698.  
  699. { -----------------------   CUT HERE  -----------------------------------  }
  700.  
  701. {  -------------     ASSEMBLER CODE FOR TPWRDSTR.ASM  -------------------  }
  702. {  USE TASM TO COMPILE }
  703. ;******************************************************
  704. ;                  TPWRDSTR.ASM 1.0
  705. ;             WrdStr string manipulation
  706. ;        Copyright (c) TurboPower Software 1987.
  707. ; Portions copyright (c) Sunny Hill Software 1985, 1986
  708. ;     and used under license to TurboPower Software
  709. ;                All rights reserved.
  710. ;******************************************************
  711.  
  712.         INCLUDE TPCOMMON.ASM
  713.  
  714. ;****************************************************** Code
  715.  
  716. CODE    SEGMENT BYTE PUBLIC
  717.  
  718.         ASSUME  CS:CODE
  719.  
  720.         PUBLIC  Search
  721.  
  722.         EXTRN   UpCasePrim : FAR
  723.         EXTRN   LoCasePrim : FAR
  724.  
  725. Upcase  MACRO                           ;UpCase character in AL
  726.         PUSH   BX
  727.         CALL   UpCasePrim
  728.         POP    BX
  729.         ENDM
  730.  
  731. Locase  MACRO                           ;LoCase character in AL
  732.         PUSH   BX
  733.         CALL   LoCasePrim
  734.         POP    BX
  735.         ENDM
  736.  
  737. ;****************************************************** Search
  738.  
  739. ;  function Search(var Buffer; BufLength : Word;
  740. ;                  var Match;  MatLength : Word) : Word; external;
  741. ;Search through Buffer for Match.
  742. ;BufLength is length of range to search.
  743. ;MatLength is length of string to match
  744. ;Returns number of bytes searched to find St, FFFF if not found
  745.  
  746. ;equates for parameters:
  747. MatLength       EQU     WORD PTR [BP+6]
  748. Match           EQU     DWORD PTR [BP+8]
  749. BufLength       EQU     WORD PTR  [BP+0Ch]
  750. Buffer          EQU     DWORD PTR [BP+0Eh]
  751.  
  752. Search  PROC FAR
  753.  
  754.         StackFrameBP
  755.         PUSH    DS                      ;Save DS
  756.         CLD                             ;Go forward
  757.  
  758.         LES     DI,Buffer               ;ES:DI => Buffer
  759.         MOV     BX,DI                   ;BX = Ofs(Buffer)
  760.  
  761.         MOV     CX,BufLength            ;CX = Length of range to scan
  762.         MOV     DX,MatLength            ;DX = Length of match string
  763.  
  764.         TEST    DX,DX                   ;Length(Match) = 0?
  765.         JZ      Error                   ;If so, we're done
  766.  
  767.         LDS     SI,Match                ;DS:SI => Match buffer
  768.         LODSB                           ;AL = Match[1]; DS:SI => Match[2]
  769.         DEC     DX                      ;DX = MatLength-1
  770.         SUB     CX,DX                   ;CX = BufLength-(MatLength-1)
  771.         JBE     Error                   ;Error if BufLength is less
  772.  
  773. ;Search for first character in St
  774. Next:   REPNE   SCASB                   ;Search forward for Match[1]
  775.         JNE     Error                   ;Done if not found
  776.         TEST    DX,DX                   ;If Length = 1 (DX = 0) ...
  777.         JZ      Found                   ; the "string" was found
  778.  
  779.         ;Search for remainder of St
  780.  
  781.         PUSH    CX                      ;Save CX
  782.         PUSH    DI                      ;Save DI
  783.         PUSH    SI                      ;Save SI
  784.  
  785.         MOV     CX,DX                   ;CX = Length(St) - 1
  786.         REPE    CMPSB                   ;Does rest of string match?
  787.  
  788.         POP     SI                      ;Restore SI
  789.         POP     DI                      ;Restore DI
  790.         POP     CX                      ;Restore CX
  791.  
  792.         JNE     Next                    ;Try again if no match
  793.  
  794. ;Calculate number of bytes searched and return in St
  795. Found:  DEC     DI                      ;DX = Offset where found
  796.         MOV     AX,DI                   ;AX = Offset where found
  797.         SUB     AX,BX                   ;Subtract starting offset
  798.         JMP     Short Done              ;Done
  799.  
  800. ;Match was not found
  801. Error:  XOR     AX,AX                   ;Return
  802.         DEC     AX                      ;Return FFFF
  803.  
  804. Done:   POP     DS                      ;Restore DS
  805.         ExitCode 10
  806.  
  807. Search  ENDP
  808.  
  809. CODE    ENDS
  810.  
  811.         END
  812. { END OF TPWRDSTR.ASM }
  813. {-------------------------------   CUT HERE ------------------------- }
  814.